package com.mygdx.game.group;

import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.mygdx.game.MainGame;
import com.mygdx.game.group.basegroup.BaseGroup;
import com.mygdx.game.resource.Res;

import java.util.Random;


public class MiddleGroup extends BaseGroup {
    /**
     * 4x4
     */
    final int SIZE = 4;
    private CardGroup[][] cardGroup = new CardGroup[SIZE][SIZE];

    /**
     * 随机数生成器
     */
    private Random random;

    /**
     * 记录卡片数据是否发生相加
     */
    boolean isCumulated = false;
    /**
     * 记录卡片位置是否发生变化
     */
    boolean isChanged = false;
    /**
     * 移动和合并音效
     * */
    private Sound moveSound;
    private Sound mergeSound;


    public MiddleGroup(MainGame mainGame) {
        super(mainGame);
        init();
    }

    public void init() {
        //以系统时间作为种子
        random = new Random();
        random.setSeed(System.currentTimeMillis());
        setSize(getMainGame().getWorldWidth() - 20, getMainGame().getWorldWidth() - 20);
        //背景
        Image bgImage = new Image(getMainGame().getTextureAtlas().findRegion(Res.Atlas.GAME_RECT_BG));
        bgImage.setSize(getWidth(), getHeight());
        addActor(bgImage);

        moveSound = getMainGame().getAssetManager().get(Res.Audio.MOVE,Sound.class);
        mergeSound = getMainGame().getAssetManager().get(Res.Audio.MERGE,Sound.class);
        /**
         * 初始化卡片
         */
        cardInit();
        addListener(new InputListenerImpl());
    }

    public void cardInit(){
        /**
         * x,y方向上一个单位的数值
         */
        float xUnit = getWidth() / 4;
        float yUnit = getHeight() / 4;
        /**
         * 初始化卡片
         */
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                cardGroup[i][j] = new CardGroup(getMainGame(), 0);
                cardGroup[i][j].setPosition(j * xUnit + 8,(3 - i) * yUnit + 8);
                //cardGroup[i][j].setData(i*4+j);
                addActor(cardGroup[i][j]);
            }
        }
        //开始时刷新两个卡片
        randomData(2);
    }

    /**
     * 随机给一个卡片赋值
     * 0.3的概率是4
     * 0.7是2
     *
     * @param count
     * 卡片的数量
     */
    public void randomData(int count) {
        while (count-- >= 1) {
            int x = random.nextInt(4);
            int y = random.nextInt(4);
            if (cardGroup[x][y].getData() != 0) {
                count++;
                continue;
            }
            cardGroup[x][y].setData(random.nextDouble() >= 0.3 ? 2 : 4);
        }
    }

    /**
     * 输入监听器的实现
     */
    private class InputListenerImpl extends InputListener {

        private float downX;
        private float downY;

        @Override
        public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
            downX = x;
            downY = y;
            return true;
        }

        @Override
        public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
            float diffX = x - downX;
            float diffY = y - downY;

            if (Math.abs(diffX) >= 20 && Math.abs(diffX) * 0.5F > Math.abs(diffY)) {
                // 左右滑动
                if (diffX > 0) {
                    toRight();
                } else {
                    toLeft();
                }
            } else if (Math.abs(diffY) >= 20 && Math.abs(diffY) * 0.5F > Math.abs(diffX)) {
                // 上下滑动
                if (diffY > 0) {
                    toUp();
                } else {
                    toDown();
                }
            }
            if (isOver()){
                getMainGame().getGameScreen().setShowGameOverStage(true);
            }
        }
    }


    public void toLeft(){
        moveSound.play();
        for (int i = 0;i<4;i++) {
            /*
             * 第一次循环将所有的0挤到相反的方向
             */
            for (int j = 0; j < 4; j++) {
                if (cardGroup[i][j].getData() == 0) {
                    //到达边界直接跳出循环
                    if (j==3)
                        continue;
                    //发现0之后，向0的后方寻找不为0的卡片并与0交换数据
                    for (int tmp = j+1;tmp<4;tmp++){
                        if (cardGroup[i][tmp].getData() != 0){
                            swap(cardGroup[i][j],cardGroup[i][tmp]);
                            break;
                        }
                    }
                }
            }
            /*
             * 第二次循环将相等的卡片相加
             */
            for (int j = 0; j < 3; j++) {
                if (cardGroup[i][j].getData() == 0) continue;
                if (cardGroup[i][j].getData() == cardGroup[i][j + 1].getData()) {
                    cumulate(cardGroup[i][j], cardGroup[i][j + 1]);
                }
            }

            /*
             * 合并过后的数据再次把0挤到相反的方向
             */
            for (int j = 0; j < 4; j++) {
                if (cardGroup[i][j].getData() == 0) {
                    if (j==3)
                        continue;
                    for (int tmp = j+1;tmp<4;tmp++){
                        if (cardGroup[i][tmp].getData() != 0){
                            swap(cardGroup[i][j],cardGroup[i][tmp]);
                            break;
                        }
                    }
                }
            }
        }
        music();
    }

    public void toRight(){
        moveSound.play();
        for (int i = 0;i<4;i++) {
            for (int j = 3; j >= 0; j--) {
                if (cardGroup[i][j].getData() == 0) {
                    if (j==0)
                        continue;
                    for (int tmp = j-1;tmp>=0;tmp--){
                        if (cardGroup[i][tmp].getData() != 0){
                            swap(cardGroup[i][j],cardGroup[i][tmp]);
                            break;
                        }
                    }
                }
            }
            for (int j = 3; j > 0; j--) {
                if (cardGroup[i][j].getData() == 0) continue;
                if (cardGroup[i][j].getData() == cardGroup[i][j - 1].getData()) {
                    cumulate(cardGroup[i][j], cardGroup[i][j - 1]);
                }
            }
            for (int j = 3; j >= 0; j--) {
                if (cardGroup[i][j].getData() == 0) {
                    if (j==0)
                        continue;
                    for (int tmp = j-1;tmp>=0;tmp--){
                        if (cardGroup[i][tmp].getData() != 0){
                            swap(cardGroup[i][j],cardGroup[i][tmp]);
                            break;
                        }
                    }
                }
            }
        }
        music();
    }

    public void toUp(){
        moveSound.play();

        for (int i = 0;i<4;i++) {
            for (int j = 0; j <4; j++) {
                if (cardGroup[j][i].getData() == 0) {
                    if (j==0)
                        continue;
                    for (int tmp = j+1;tmp<4;tmp++){
                        if (cardGroup[tmp][i].getData() != 0){
                            swap(cardGroup[j][i],cardGroup[tmp][i]);
                            break;
                        }
                    }
                }
            }
            for (int j = 0; j < 3; j++) {
                if (cardGroup[j][i].getData() == 0) continue;
                if (cardGroup[j][i].getData() == cardGroup[j+1][i].getData()) {
                    cumulate(cardGroup[j][i], cardGroup[j+1][i]);
                }
            }
            for (int j = 0; j <4; j++) {
                if (cardGroup[j][i].getData() == 0) {
                    if (j==3)
                        continue;
                    for (int tmp = j+1;tmp<4;tmp++){
                        if (cardGroup[tmp][i].getData() != 0){
                            swap(cardGroup[j][i],cardGroup[tmp][i]);
                            break;
                        }
                    }
                }
            }
        }
        music();
    }

    public void toDown(){
        moveSound.play();

        for (int i = 0;i<4;i++) {
            for (int j = 3; j >= 0; j--) {
                if (cardGroup[j][i].getData() == 0) {
                    if (j==0)
                        continue;
                    for (int tmp = j-1;tmp>=0;tmp--){
                        if (cardGroup[tmp][i].getData() != 0){
                            swap(cardGroup[j][i],cardGroup[tmp][i]);
                            break;
                        }
                    }
                }
            }
            for (int j = 3; j > 0; j--) {
                if (cardGroup[j][i].getData() == 0) continue;
                if (cardGroup[j][i].getData() == cardGroup[j-1][i].getData()) {
                    cumulate(cardGroup[j][i], cardGroup[j-1][i]);
                }
            }
            for (int j = 3; j >= 0; j--) {
                if (cardGroup[j][i].getData() == 0) {
                    if (j==0)
                        continue;
                    for (int tmp = j-1;tmp>=0;tmp--){
                        if (cardGroup[tmp][i].getData() != 0){
                            swap(cardGroup[j][i],cardGroup[tmp][i]);
                            break;
                        }
                    }
                }
            }
        }
        music();

    }

    private void music(){
        if (isChanged || isCumulated){
            //位置发生改变时生成随机卡片
            randomData(1);
        }
        if (isCumulated){
            mergeSound.play();
        }
        isCumulated = false;
        isChanged = false;
    }

    private boolean isOver(){
        for (int i = 0;i<SIZE;i++){
            for (int j = 0;j<SIZE-1 ;j++){
                if (cardGroup[i][j].getData() == 0){
                    return false;
                }
                if (cardGroup[i][j].getData()==cardGroup[i][j+1].getData()){
                    return false;
                }
                if (cardGroup[j][i].getData()==cardGroup[j+1][i].getData()){
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 累加运算
     */
    private final void cumulate(CardGroup one,CardGroup two){
        int temp = one.getData() + two.getData();
        one.setData(temp);
        two.setData(0);
        getMainGame().getGameScreen().getHomeStage().getTopGroup().addCurrentScore(temp);
        isCumulated = true;
    }
    private final void swap(CardGroup one,CardGroup two){
        one.setData(two.getData()+one.getData());
        two.setData(0);
        isChanged = true;
    }

    public void reStart(){
        cardInit();
    }
}
